package ru.stepuk.modeller;

import java.util.HashMap;
import ru.stepuk.modeller.events.Event;
import java.util.Map;

/**
 *
 * @author ivan
 */
public class Timeline implements Runnable {

    private Map<Integer, Event> scedule = new HashMap<Integer, Event>();
    private final int RATE = 100;
    private boolean stopped = true;
    private int time = -1;
    //TODO add time scale private double timeScale = 1.0;
    //TODO step -> step <-

    public void run() {
        while (true) {
            while (stopped) {
            }
            time++;
            if (scedule.containsKey(time)) {
                scedule.get(time).process();
            }
            sleep();
        }
    }

    public void pause() {
        stopped = true;
    }

    public void play() {
        stopped = false;
    }

    public void stop() {
        stopped = true;
        time = -1;
    }

    public void fastForward() {
        while (true) {
            time++;
            if (scedule.containsKey(time)) {
                scedule.get(time).process();
            }
        }
    }

    public void stepForward() {
        while (true) {
            time++;
            if (scedule.containsKey(time)) {
                scedule.get(time).process();
                break;
            }
        }
    }

    public void stepBack() {
    }

    public double getCurrentTime() {
        return time / RATE;
    }

    public void addEvent(double time, Event event) {
        int tick = secondsToTicks(time);
        while (scedule.containsKey(tick)) {
            tick++;
        }
        scedule.put(tick, event);
    }

    public void appendEvent(double interval, Event event) {
        int tick = this.time + secondsToTicks(interval);
        while (scedule.containsKey(tick)) {
            tick++;
        }
        scedule.put(tick, event);
    }

    public void deleteEvent(double time) {
        int tick = secondsToTicks(time);
        scedule.remove(tick);
    }

    private int secondsToTicks(double time) {
        return (int) (time * RATE);
    }

    private void sleep() {
        try {
            Thread.sleep(1000 / RATE);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}
